package com.laogao.logback;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.laogao.model.LogMessage;
import com.laogao.model.LogRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.List;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

@Component
public class LogWebSocketHandler extends TextWebSocketHandler {

    private static final int MAX_LOG_ENTRIES = 1000;
    private final ObjectMapper objectMapper = new ObjectMapper();
    // 保存最新日志的缓存
    private final ConcurrentLinkedDeque<LogMessage> logCache = new ConcurrentLinkedDeque<>();
    // 保存所有活动的 WebSocket session
    private final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();

    // 用于让 Logback Appender 获取本类实例（静态单例写法）
    private static LogWebSocketHandler instance;

    public LogWebSocketHandler() {
        instance = this;
    }

    public static LogWebSocketHandler getInstance() {
        return instance;
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.add(session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        sessions.remove(session);
    }

    /**
     * 当接收到客户端消息时，解析为 LogRequest，然后从缓存中筛选日志返回（只返回满足条件的最新日志）
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        LogRequest logRequest = objectMapper.readValue(message.getPayload(), LogRequest.class);
        // 筛选缓存中符合请求级别的日志
        List<LogMessage> filtered = logCache.stream()
                .filter(log -> log.getLevel().equalsIgnoreCase(logRequest.getLevel()))
                .collect(Collectors.toList());
        // 取最新的 lineCount 条日志（若数量不足，则全部返回）
        if (filtered.size() > logRequest.getLineCount()) {
            filtered = filtered.subList(filtered.size() - logRequest.getLineCount(), filtered.size());
        }
        // 将每条日志依次返回给当前 session
        for (LogMessage log : filtered) {
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(log)));
        }
    }

    /**
     * 添加日志到内存缓存，并广播新日志给所有连接的客户端
     */
    public void addLog(LogMessage logMessage) {
        synchronized (logCache) {
            if (logCache.size() >= MAX_LOG_ENTRIES) {
                logCache.pollFirst();
            }
            logCache.addLast(logMessage);
        }
        broadcastLogMessage(logMessage);
    }

    /**
     * 向所有活动 session 广播日志消息
     */
    public void broadcastLogMessage(LogMessage logMessage) {
        try {
            String payload = objectMapper.writeValueAsString(logMessage);
            for (WebSocketSession session : sessions) {
                if (session.isOpen()) {
                    session.sendMessage(new TextMessage(payload));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
